package com.lwy.domain;



import org.springframework.format.annotation.DateTimeFormat;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class SendCarDemo {
    public static void main(String[] args) throws ParseException {

        //初始化车辆
        List<Vehicle> vehicles = getVehicles();

        Random random = new Random();


        //获取当前年的每一个月
        List<LocalDate> months = getEveryMonthOfYear();
        int yearCount = 0;


        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");


        for (LocalDate month : months) {

            //获取当前月的每一天
            List<LocalDate> dates = getEveryDayOfMonth(month);
            String monthFormat = formatter.format(month);


            /**
             * 生成订单 当前月 每一天 三条线路
             * 线路 罐子沟到准大煤泥 20-40
             * 线路 罐子沟到建投煤泥 10-20
             * 线路 罐子沟到点岱沟粉煤 90-110
             */
            List<Order> orderList = getOrderList(dates, random);

            System.out.println(monthFormat + "生成的订单总数:" + orderList.size());

            // 随机打乱
            Collections.shuffle(orderList);

            Dispatcher dispatcher = new Dispatcher(vehicles);

            MonthlyStatistics monthlyStatistics = new MonthlyStatistics();

            for (Order order : orderList) {
                //发放订单
                dispatcher.addOrder(order, random);

                //每天 每条线单量
                monthlyStatistics.addOrder(order);
            }



            // 打印方便查看
            System.out.println("----------------------------------");
            //总单量
            int orderCount = 0;
            //每条线上总单量
            Map<String, Integer> orderCountsmap = new HashMap<>();

            for (Vehicle vehicle : vehicles) {
                // 1 每车总单量
                int carCount = 0;
                Map<String, Integer> orderCarMap = vehicle.getOrderCountsByRoute();

                for (Integer count : orderCarMap.values()) {
                    carCount += count;
                    orderCount += count;
                }
                System.out.println("2024-01 - " + monthFormat + " ---"+ vehicle.getCarId() + "：总单量：" + carCount + "每条线信息：" + orderCarMap);

                // 2 计算每条线上总单量
                for (Map.Entry<String, Integer> stringIntegerEntry : orderCarMap.entrySet()) {
                    String key = stringIntegerEntry.getKey();
                    Integer value = stringIntegerEntry.getValue();
                    Integer count = orderCountsmap.get(key);
                    if (Objects.isNull(count) || count == 0){
                        orderCountsmap.put(key,value);
                    }else {
                        orderCountsmap.put(key, count + value);
                    }
                }
            }
            System.out.println("----------------------------------");
            for (Map.Entry<String, Integer> stringIntegerEntry : orderCountsmap.entrySet()) {
                System.out.println("2024-01 - " + monthFormat + " 这条线：" + stringIntegerEntry.getKey() + "--总单量--:" + stringIntegerEntry.getValue());
            }
            System.out.println("----------------------------------");
            // 3 总单量
            System.out.println("2024-01 - " + monthFormat + "总单量----:"+ orderCount);

            yearCount += orderCount;
            System.out.println("----------------------------------");

            // 4 每天每条线单量
            Map<LocalDate, Map<String, Integer>> dailyOrderCountsByRoute = monthlyStatistics.getDailyOrderCountsByRoute();
            for (Map.Entry<LocalDate, Map<String, Integer>> localDateMapEntry : dailyOrderCountsByRoute.entrySet()) {
                LocalDate localDate = localDateMapEntry.getKey();
                Map<String, Integer> value = localDateMapEntry.getValue();
                System.out.println(localDate + " 每条线信息单量:" + value);
            }
            System.out.println("----------------------------------");
        }

        //实际代码应用  redis hash？？？


    }

    /**
     * 获取当前年的每一个月
     * @return
     */
    private static List<LocalDate> getEveryMonthOfYear() {
        LocalDate today = LocalDate.now();
        LocalDate firstDayOfYear = today.with(TemporalAdjusters.firstDayOfYear());
        LocalDate lastDayOfYear = today.with(TemporalAdjusters.lastDayOfYear());
        return Stream.iterate(firstDayOfYear, d -> d.plusMonths(1))
                .limit(ChronoUnit.MONTHS.between(firstDayOfYear, lastDayOfYear) + 1)
                .collect(Collectors.toList());
    }


    private static List<Order> getOrderList(List<LocalDate> dates, Random random) {
        List<Order> orderList = new ArrayList<>();
        for (LocalDate date : dates) {
            //三条线路
            String routeIdOne = "罐子沟到准大煤泥";
            int minOne = 20;
            int maxOne = 40;
            int randomOne = getRandomInt(minOne, maxOne, random);
            for (int i = 0; i < randomOne; i++) {
                Order order = new Order();
                order.setDate(date);
                order.setOrderId(UUID.randomUUID().toString().replace("-", ""));
                order.setRouteId(routeIdOne);
                orderList.add(order);
            }

            String routeIdTwo = "罐子沟到建投煤泥";
            int minTwo = 10;
            int maxTwo = 20;
            int randomTwo = getRandomInt(minTwo, maxTwo, random);
            for (int i = 0; i < randomTwo; i++) {
                Order order = new Order();
                order.setDate(date);
                order.setOrderId(UUID.randomUUID().toString().replace("-", ""));
                order.setRouteId(routeIdTwo);
                orderList.add(order);
            }

            String routeIdThree = "罐子沟到点岱沟粉煤";
            int minThree = 90;
            int maxThree = 110;
            int randomThree = getRandomInt(minThree, maxThree, random);
            for (int i = 0; i < randomThree; i++) {
                Order order = new Order();
                order.setDate(date);
                order.setOrderId(UUID.randomUUID().toString().replace("-", ""));
                order.setRouteId(routeIdThree);
                orderList.add(order);
            }
        }
        return orderList;

    }

    private static int getRandomInt(int min, int max,Random random) {
        return random.nextInt(max) % (max - min + 1) + min;
    }

    /**
     * 获取当前时间月的每一天
     * @return
     */
    private static List<LocalDate> getEveryDayOfMonth(LocalDate date) {
        LocalDate firstDayOfMonth = date.with(TemporalAdjusters.firstDayOfMonth());
        LocalDate lastDayOfMonth = date.with(TemporalAdjusters.lastDayOfMonth());
        return Stream.iterate(firstDayOfMonth, d -> d.plusDays(1))
                .limit(ChronoUnit.DAYS.between(firstDayOfMonth, lastDayOfMonth) + 1)
                .collect(Collectors.toList());
    }

    private static List<Vehicle> getVehicles() {
        return Arrays.asList(new Vehicle("蒙KD3538"),
                new Vehicle("蒙KE7266"),new Vehicle("蒙KE2492"),new Vehicle("蒙KE3340"),
                new Vehicle("蒙KD6961"),new Vehicle("蒙KD3531"),new Vehicle("蒙KD7973"),
                new Vehicle("蒙KD2600"),new Vehicle("蒙KD3975"),new Vehicle("蒙KD8307"),
                new Vehicle("蒙KB6910"),new Vehicle("蒙KD5757"),new Vehicle("蒙KB7448"),
                new Vehicle("蒙KE2379"),new Vehicle("蒙KE3787"),new Vehicle("蒙KE5249"),
                new Vehicle("蒙KD9875"),new Vehicle("蒙KJ9947"),new Vehicle("蒙KD9038"),
                new Vehicle("蒙KD9278"),new Vehicle("蒙KJ3566"),new Vehicle("蒙KJ3561"),
                new Vehicle("蒙KK5859"),new Vehicle("蒙KD5191"),new Vehicle("蒙KE9010"),
                new Vehicle("蒙KB0748"),new Vehicle("蒙KD9908"),new Vehicle("蒙KB0428"),
                new Vehicle("蒙KB2847"),new Vehicle("蒙KD3806"),new Vehicle("蒙KH6851"),
                new Vehicle("蒙KD7766"),new Vehicle("蒙KD2033"),new Vehicle("蒙KD5586"),
                new Vehicle("蒙KD2111"),new Vehicle("蒙KD8017"),new Vehicle("蒙KD9821"),
                new Vehicle("蒙KK8582"),new Vehicle("蒙KK9035"),new Vehicle("蒙KD5380"),
                new Vehicle("蒙KE6628"),new Vehicle("蒙KG2294"),new Vehicle("蒙KE5898"),
                new Vehicle("蒙KD9583"),new Vehicle("蒙KE5653"),new Vehicle("蒙KD8652"),
                new Vehicle("蒙KG5647"),new Vehicle("蒙KD6191"),new Vehicle("蒙KE3679"),
                new Vehicle("蒙KJ3250"),new Vehicle("蒙KH4185"),new Vehicle("蒙KK7306"),
                new Vehicle("蒙KD8723"),new Vehicle("蒙KB2257"),new Vehicle("蒙KD6825"),
                new Vehicle("蒙KD7395"),new Vehicle("蒙KE6838"),new Vehicle("蒙KD5099"),
                new Vehicle("蒙KD5650"),new Vehicle("蒙KE2033"),new Vehicle("蒙KJ6531"),
                new Vehicle("蒙KE8813"),new Vehicle("蒙KE9626"),new Vehicle("蒙KD9052"),
                new Vehicle("蒙KD9293"),new Vehicle("蒙KK1579"),new Vehicle("蒙KE9159"),
                new Vehicle("蒙KD9329"),new Vehicle("蒙KD6730"),new Vehicle("蒙KB4521"),
                new Vehicle("蒙KD5766"),new Vehicle("蒙KE9917"),new Vehicle("蒙KE5833"),
                new Vehicle("蒙KE2322"),new Vehicle("蒙KD9363"),new Vehicle("蒙KB6301"),
                new Vehicle("蒙KK7150"),new Vehicle("蒙KD7223"),new Vehicle("蒙KD3781"),
                new Vehicle("蒙KD5089"),new Vehicle("蒙KE2561"),new Vehicle("蒙KE9875"),
                new Vehicle("蒙KJ8521"),new Vehicle("蒙KE7811"),new Vehicle("蒙KD9361"),
                new Vehicle("蒙KE6723"),new Vehicle("蒙KE7218")
        );
    }

    /**
     * 订单线路信息类
     */
    static class Order{
        /**
         * 订单id
         */
        private String orderId;

        /**
         * 路线id
         */
        private String routeId;

        /**
         * 订单时间
         */
        private LocalDate date;

        public String getOrderId() {
            return orderId;
        }
        public void setOrderId(String orderId) {
            this.orderId = orderId;
        }
        public String getRouteId() {
            return routeId;
        }
        public void setRouteId(String routeId) {
            this.routeId = routeId;
        }
        public LocalDate getDate() {
            return date;
        }
        public void setDate(LocalDate date) {
            this.date = date;
        }

        @Override
        public String toString() {
            return "Order{" +
                    "orderId='" + orderId + '\'' +
                    ", routeId='" + routeId + '\'' +
                    ", date=" + date +
                    '}';
        }
    }

    /**
     * 车辆信息类
     */
    static class Vehicle{

        /**
         * 车辆id
         */
        private String carId;

        /**
         *  String 线路  Integer 订单数量
         */
        private Map<String,Integer> orderCountsByRoute;

        public Map<String, Integer> getOrderCountsByRoute() {
            return orderCountsByRoute;
        }

        public String getCarId() {
            return carId;
        }

        public void setCarId(String carId) {
            this.carId = carId;
        }

        public void setOrderCountsByRoute(Map<String, Integer> orderCountsByRoute) {
            this.orderCountsByRoute = orderCountsByRoute;
        }

        public Vehicle(String carId) {
            this.carId = carId;
            this.orderCountsByRoute = new HashMap<>();
        }

        public void addOrder(String routeId) {
            this.orderCountsByRoute.merge(routeId, 1, Integer::sum);
        }

        public int getOrderCountForRoute(String routeId) {
            return this.orderCountsByRoute.getOrDefault(routeId, 0);
        }

        @Override
        public String toString() {
            return "Vehicle " + carId + ": " + orderCountsByRoute;
        }
    }

    /**
     * 负责车辆管理列表 并提供方式分配新的订单给车辆
     */
    static class Dispatcher{
        private List<Vehicle> vehicles;

        public Dispatcher(List<Vehicle> vehicles) {
            this.vehicles = vehicles;
        }

        public void addOrder(Order order,Random random){
            Vehicle minOrderVehicle = null;
            int minOrders = Integer.MAX_VALUE;
            // 随机选取车辆
            Collections.shuffle(vehicles);

            for (Vehicle vehicle : vehicles) {
                int orderCountForRoute = vehicle.getOrderCountForRoute(order.getRouteId());
                // 这里
                if (orderCountForRoute < minOrders) {
                    minOrders = orderCountForRoute;
                    minOrderVehicle = vehicle;
                }
            }
            minOrderVehicle.addOrder(order.getRouteId());
        }
    }

    /**
     * 每天某条线的订单数量，并计算每个月每天的平均订单分配情况
     */
    static class MonthlyStatistics{
        /**
         * 时间 -> 线路id -> 订单量
         */
        private Map<LocalDate,Map<String,Integer>> dailyOrderCountsByRoute;

        public Map<LocalDate, Map<String, Integer>> getDailyOrderCountsByRoute() {
            return dailyOrderCountsByRoute;
        }

        public MonthlyStatistics() {
            this.dailyOrderCountsByRoute = new HashMap<>();
        }

        public void addOrder(Order order) {
            LocalDate date = order.getDate();
            Map<String, Integer> routeCounts = dailyOrderCountsByRoute.computeIfAbsent(date, k -> new HashMap<>());
            routeCounts.merge(order.getRouteId(), 1, Integer::sum);
        }


        // - - 搁置 ----
        public Map<String, Double> getAverageOrdersPerDayForMonth(LocalDate monthStart) {
            Map<String, Double> averageOrdersPerDay = new HashMap<>();
            LocalDate monthEnd = monthStart.plusMonths(1).minusDays(1);

            for (int day = monthStart.getDayOfMonth(); day <= monthEnd.getDayOfMonth(); day++) {
                LocalDate date = LocalDate.of(monthStart.getYear(), monthStart.getMonth(), day);
                Map<String, Integer> routeCounts = dailyOrderCountsByRoute.get(date);

                if (routeCounts != null) {
                    for (Map.Entry<String, Integer> entry : routeCounts.entrySet()) {
                        String routeId = entry.getKey();
                        int orderCount = entry.getValue();
                        averageOrdersPerDay.merge(routeId, (double) orderCount, (oldVal, newVal) -> oldVal + newVal);
                    }
                }
            }
            for (Map.Entry<String, Double> entry : averageOrdersPerDay.entrySet()) {
                String routeId = entry.getKey();
                double totalOrders = entry.getValue();
                int daysInMonth = monthEnd.getDayOfMonth();
                double average = totalOrders / daysInMonth;
                averageOrdersPerDay.put(routeId, average);
            }

            return averageOrdersPerDay;
        }

    }

}


